﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1.ExpressionTrees
{
    internal class TransateExpressionTrees
    {
        public static void Show()
        {
            /*Funcvar one = Expression.Constant(1, typeof(int));
            var two = Expression.Constant(2, typeof(int));
            var addition = Expression.Add(one, two);
            var sum = ReplaceNodes(addition);
            var executableFunc = Expression.Lambda(sum);
            var func = (Func<int>)executableFunc.Compile();
            Console.WriteLine(func());

            var three = Expression.Constant(3, typeof(int));
            var four = Expression.Constant(4, typeof(int));
            var add2 = Expression.Add(three, four);
            var sum2 = Expression.Add(addition, add2);
            <Expression, int> aggregate = null!;
            aggregate = (exp) =>
                exp.NodeType == ExpressionType.Constant ? (int)((ConstantExpression)exp).Value! :
                    aggregate(((BinaryExpression)exp).Left) + aggregate(((BinaryExpression)exp).Right);
            var theSum = Aggregate(sum2);
            Console.WriteLine(theSum);*/

            Expression<Func<int>> sum1 = ()=>1+(2+(3+4));
            Aggregate(sum1 );

        }

        /// <summary>
        /// 作用：把一个常量元素的表达式乘以10然后在返回。
        /// </summary>
        /// <param name="original"></param>
        /// <returns></returns>
        private static Expression ReplaceNodes(Expression original)
        {
            if (original.NodeType == ExpressionType.Constant)
            {
                return Expression.Multiply(original, Expression.Constant(10));
            }
            else if (original.NodeType == ExpressionType.Add)
            {
                var binaryExpression = original as BinaryExpression;
                return Expression.Add(
                        ReplaceNodes(binaryExpression.Left),
                        ReplaceNodes(binaryExpression.Right)
                    );
            }
            return original;
        }


        private static int Aggregate(Expression exp)
        {
            if (exp.NodeType == ExpressionType.Constant)
            {
                var constantExp = exp as ConstantExpression;
                Console.Error.WriteLine($"Found Constant:{constantExp.Value}");
                if (constantExp.Value is int value)
                {
                    return value;
                }
                else
                {
                    return 0;
                }
            }
            else if (exp.NodeType == ExpressionType.Add)
            {
                var addExp = (BinaryExpression)exp;
                Console.Error.WriteLine("Found Addition Expression");
                Console.Error.WriteLine("Computing Left node");
                var leftOperand = Aggregate(addExp.Left);
                Console.Error.WriteLine($"Left is: {leftOperand}");
                Console.Error.WriteLine("Computing Right node");
                var rightOperand = Aggregate(addExp.Right);
                Console.Error.WriteLine($"Right is:{rightOperand}");
                var sum = leftOperand + rightOperand;
                Console.Error.WriteLine($"Computed sum:{sum}");
                return sum;
            }
            else
            {
                throw new NotSupportedException("Haven't written this yet");
            }
        }

    }
}
